package com.tuling.jvm.classloader;

import java.io.*;
import java.lang.reflect.Method;

/**
 * Created by chenhs on 2018/7/31.
 *
 * 深入探讨 Java 类加载器【***堪称范本***】
 * https://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html
 *
 */
public class FileSystemClassLoader extends ClassLoader {

    private String rootDir;

    public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    private String getClassNameToPath(String className) {
        return rootDir + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
    }

    private byte[] getClassData(String className) {
        String path = getClassNameToPath(className);

        try {
            InputStream ins = new FileInputStream(path);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bufferSize = 4096;
            int bytesNumRead = 0;
            byte[] buffer = new byte[bufferSize];
            while ((bytesNumRead = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesNumRead);
            }
            return baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    public static void main(String[] args) throws Exception {
        FileSystemClassLoader classLoader = new FileSystemClassLoader("D:/dev_tool");
        Class clazz = classLoader.loadClass("com.cn.gupao.load.Test");
        Object obj = clazz.newInstance();
        Method helloMethod = clazz.getDeclaredMethod("hello", null);
        helloMethod.invoke(obj, null);
    }
}
